/*
 * 文件名:ServiceLocator.java
 * 创建时间:2009-03-10
 * 版本:1.0
 * 版权所有:杨涛
 */
package com.yangtao.framework.service;

import com.yangtao.framework.common.SystemConstant;
import com.yangtao.framework.util.ResourceLoader;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.ContextLoader;

import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.io.InputStream;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * 服务定位器
 *
 * @author 杨涛
 * @date 2009-07-04
 * @修改者:
 * @修改时间:
 * @修改原因:
 * @版本:1.2
 */
public class ServiceLocator {

	private static ServiceLocator _instance = new ServiceLocator();
	// ejb容器参数
	private InitialContext initialContext;
	// spring容器
	private ApplicationContext applicationContext;
	// ejb本地缓存
	private Map<String, Object> cache;

	/**
	 *
	 */
	private ServiceLocator() throws BussinessException {
		try {
			if ("ejb".equals(SystemConstant.CONTAINER_TYPE)) {
				Properties props = new Properties();
				InputStream is = ResourceLoader.getInstance().getResource(
						"ejb.properties");
				props.load(is);
				initialContext = new InitialContext(props);
				cache = Collections
						.synchronizedMap(new HashMap<String, Object>());
			} else if ("spring".equals(SystemConstant.CONTAINER_TYPE)) {
				if (applicationContext == null) {
					applicationContext = ContextLoader
							.getCurrentWebApplicationContext();
				}
			}
		} catch (NamingException ne) {
			throw new BussinessException(ne);
		} catch (Exception e) {
			throw new BussinessException(e);
		}
	}

	/**
	 * 返回本类的唯一实例
	 *
	 * @return ManagerLocator对象
	 */
	public static ServiceLocator getInstance() {
		return _instance;
	}

	/**
	 * 通过类名取得服务对象
	 *
	 * @param clazz 服务接口类
	 * @return the stub
	 */
	@SuppressWarnings("unchecked")
	public <T> T getService(Class<T> clazz) {
		return this.applicationContext.getBean(clazz);
	}

	/**
	 * 根据服务的名称(可以是ejb的jndi也可以是spring的bean的名称)取得服务对象
	 *
	 * @param name serviceName
	 * @return the stub
	 */
	public <T> T getService(String name) {
		return (T) service(name);
	}

	/**
	 * 从容器中取出服务对象
	 *
	 * @param name
	 * @return the stub
	 */
	private Object service(String name) {
		Object service = null;
		try {
			if ("ejb".equals(SystemConstant.CONTAINER_TYPE)) {
				String ejbName = name + "/remote";
				if (cache.containsKey(ejbName)) {
					service = cache.get(ejbName);
				} else {
					service = initialContext.lookup(ejbName);
					cache.put(ejbName, service);
				}
			} else if ("spring".equals(SystemConstant.CONTAINER_TYPE)) {
				service = applicationContext.getBean(name);
			}
		} catch (NamingException nex) {
			nex.printStackTrace();
		}
		return service;
	}

	public void setApplicationContext(ApplicationContext applicationContext) {
		this.applicationContext = applicationContext;
	}
}
